package service.wx

import org.slf4j.Logger
import org.slf4j.LoggerFactory

import com.github.kevinsawicki.http.HttpRequest

import org.apache.commons.codec.digest.DigestUtils

import org.paic.d.D

class WxPay {
	static Logger log = LoggerFactory.getLogger(WxPay.class)

	private static final URL_CREATE_ORDER = 'https://api.mch.weixin.qq.com/pay/unifiedorder'

	// get prepay id，下订单参数
	public static Map genPostParams(Map params){
		TreeMap r = [:]

		r.spbill_create_ip = params.ip

		r.total_fee = params.totalFee
		r.out_trade_no = params.tradeNo
		r.body = params.body

		if(params.attach)
			r.attach = params.attach

		r.trade_type = params.tradeType ?: 'JSAPI'
		r.openid = params.openid

		log.info('wx order - ' + r)

		r.notify_url = WxSignature.conf.payNotifyUrl
		r.appid = WxSignature.conf.appid
		r.mch_id = WxSignature.conf.mchid

		r.nonce_str = WxApi.generateNonce()
		r.sign = generateSign(r)

		r
	}

	// jssdk pay params
	public static Map genPayJsParams(String prepayId){
		TreeMap r = [:]

		r.package = 'prepay_id=' + prepayId

		r.appId = WxSignature.conf.appid
		r.timeStamp = System.currentTimeMillis()
		r.signType = 'MD5'

		r.nonceStr = WxApi.generateNonce()
		r.paySign = generateSign(r)

		r
	}

	private static String generateSign(Map params){
		String formReqBody = params.collect{it.key + '=' + it.value}.join('&')
		formReqBody += '&key=' + WxSignature.conf.payKey

		log.info(formReqBody)

		String encoded = DigestUtils.md5Hex(formReqBody)
		encoded.toUpperCase()
	}

	private static String map2xml(Map params){
		def sb = new StringBuilder()
		sb << '<xml>'
		for(one in params){
			if(!one.value)
				continue

			sb << '<'
			sb << one.key
			sb << '>'

			if(one.value instanceof Number){
				sb << one.value
			}else{

				sb << '<![CDATA['
				sb << one.value
				sb << ']]>'
			}

			sb << '</'
			sb << one.key
			sb << '>'
		}
		sb << '</xml>'

		sb.toString()
	}

	private static Map xml2map(String str){
		if(!str)
			return null

		String tmp = str.replace('<xml>', '').replace('</xml>', '')
		Map r = [:]
		
		def pat = ~/<([^>]+)>(.+)<\/[^>]+>/
		def mat = tmp =~ pat

		if(mat){
			mat.each{it ->
				r[it[1]] = it[2].replace('<![CDATA[', '').replace(']]>', '')
			}
		}
		
		r
	}

	// 获取prepay_id
	public static String getPrepayId(Map params){
		String body = map2xml(params)

		def req = HttpRequest.post(URL_CREATE_ORDER).send(body)
		String str = req.body()

		log.info('create order result - ' + str)

		if(!str.contains('<return_code>'))
			return null
		
		/*
<xml><return_code><![CDATA[SUCCESS]]></return_code>
<return_msg><![CDATA[OK]]></return_msg>
<appid><![CDATA[wx9f7507a78aa0c8f0]]></appid>
<mch_id><![CDATA[1233859202]]></mch_id>
<nonce_str><![CDATA[RUNnVfOuOiJ6nEZy]]></nonce_str>
<sign><![CDATA[65DF6B47D23B9C8C8B9D2B888AD7E4BF]]></sign>
<result_code><![CDATA[SUCCESS]]></result_code>
<prepay_id><![CDATA[wx20150603133428021367c84f0517318194]]></prepay_id>
<trade_type><![CDATA[JSAPI]]></trade_type>
</xml>
		*/
			
		def r = xml2map(str)
		r.prepay_id
	}

	// 更改本地数据库订单状态（多个表，不同的表对应不同的支付场景）
	static boolean updateOrderStatus(String table, Map info){
		final int statusBuyed = 10

		def d = D.gen()
		Map order = d.queryMap('select id, amount from ' + table + ' where trade_no = ? and openid = ?', 
			[info.out_trade_no, info.openid])
		if(!order)
			return false

		boolean flag = false
		log.warn('find order 4 ' + table + ' - ' + info.out_trade_no + ' - ' + info.openid)
		long fee = order.amount * 100
		if(fee == Long.valueOf(info.total_fee)){
			d.update([id: order.id, status: statusBuyed, dd_buyed: new Date()], table, null)
			flag = true
		}else{
			log.warn('fee not match - ' + fee + ' - remote - ' + info.total_fee)
		}

		flag
	}
}